1 00:00:00,620 --> 00:00:06,050 Hey there to progress the storyline of our game further, we need to give our players the ability to 2 00:00:06,050 --> 00:00:08,120 control the doors in our game. 3 00:00:08,120 --> 00:00:13,220 Currently, our doors have zero functionality, so we're going to have to script the functionality for 4 00:00:13,220 --> 00:00:13,670 them. 5 00:00:14,300 --> 00:00:19,310 Now, in each of these door models, I've added an attribute to define the type of the door. 6 00:00:19,310 --> 00:00:25,070 For example, these doors are single, meaning they only have one door to move, while our door in the 7 00:00:25,070 --> 00:00:30,110 front here is defined as a double door, meaning there is two hinges that need to be rotated for the 8 00:00:30,110 --> 00:00:31,730 door to open and close. 9 00:00:32,150 --> 00:00:35,630 Now we're going to open and close these doors using the tween service. 10 00:00:35,630 --> 00:00:39,920 But you may already know that playing tweens on the server is not optimal. 11 00:00:39,920 --> 00:00:44,780 This is because every step of the tween animation, the server has to constantly send out data to the 12 00:00:44,780 --> 00:00:47,900 clients to update the new property that the tween is affecting. 13 00:00:47,900 --> 00:00:51,170 This causes the tween to look choppy on the client. 14 00:00:51,170 --> 00:00:56,030 An alternative to this problem is having the server send the tween information to the clients, and 15 00:00:56,030 --> 00:00:58,100 the clients have to play the tween on their end. 16 00:00:58,100 --> 00:01:02,600 But the issue with this method is that the server will not be able to keep track of the new properties 17 00:01:02,600 --> 00:01:04,130 set on these instances. 18 00:01:04,130 --> 00:01:06,050 So how do we go about fixing this? 19 00:01:06,050 --> 00:01:10,130 Well, what we can do is we can send tween information to all of the clients. 20 00:01:10,130 --> 00:01:15,080 And then when the duration for that tween is over, we apply the goal properties of the tween on the 21 00:01:15,080 --> 00:01:15,560 server. 22 00:01:15,560 --> 00:01:20,570 This way tweens are smooth on the client, and the server is able to keep track of the properties for 23 00:01:20,570 --> 00:01:21,830 tweened instances. 24 00:01:22,820 --> 00:01:27,740 So what we're going to do is we're going to go into our server script service, and inside of here we're 25 00:01:27,740 --> 00:01:31,670 going to open up a module script we have in here called Better Between. 26 00:01:33,010 --> 00:01:37,540 Now this module script is going to act as our own custom tween service. 27 00:01:37,810 --> 00:01:42,130 So what we're going to do in here is we're first going to reference replicated storage. 28 00:01:44,590 --> 00:01:48,520 And then we're also going to create the table that's going to represent this module script. 29 00:01:48,520 --> 00:01:50,260 And we're going to call it Better Tween. 30 00:01:50,800 --> 00:01:53,020 And we'll make sure to return that at the end here. 31 00:01:54,400 --> 00:01:59,230 And then we're going to make a reference to an event inside of replicated storage called Play Tween. 32 00:01:59,230 --> 00:02:03,400 And this is the event we're going to use to send information to clients about the tweens. 33 00:02:03,400 --> 00:02:04,660 They need to play on their end. 34 00:02:04,660 --> 00:02:07,210 So we can call this play tween event. 35 00:02:07,210 --> 00:02:12,670 And it's inside of replicated storage, dot events, dot remotes, dot play tween. 36 00:02:13,000 --> 00:02:18,490 Now inside of this better tween module script, we're going to have a function in here. 37 00:02:18,490 --> 00:02:22,510 And we'll call this function basically just tween. 38 00:02:22,510 --> 00:02:26,350 And we're going to fill out this function basically the same way we would with a regular tween. 39 00:02:26,350 --> 00:02:28,960 We get passed an instance to the tween. 40 00:02:28,960 --> 00:02:31,630 We get passed tween info. 41 00:02:32,110 --> 00:02:37,750 And then we also get passed a table containing the goal properties for the particular instance. 42 00:02:38,740 --> 00:02:39,070 Now. 43 00:02:39,070 --> 00:02:45,070 Unfortunately, we are not able to send tween info data types through a remote events. 44 00:02:45,070 --> 00:02:50,350 So what we'll have to do is we'll have to unpack all the information inside of this tween info into 45 00:02:50,350 --> 00:02:55,480 a table, and then pass that table containing all the properties for the tweens to the clients. 46 00:02:55,480 --> 00:02:59,680 So basically what we could do is we could create a table in here and we're going to call it tween data. 47 00:03:00,310 --> 00:03:02,470 And this table is going to act as an array. 48 00:03:02,470 --> 00:03:05,800 So we need to fill out our tween info in order. 49 00:03:05,800 --> 00:03:13,360 So the first thing that a tween info is passed is going to be the time or the duration for this tween. 50 00:03:13,510 --> 00:03:19,480 The next thing we need to get passed inside of this tween info is going to be the easing style for the 51 00:03:19,480 --> 00:03:20,080 tween. 52 00:03:20,790 --> 00:03:25,890 The next thing we're going to get past is the easing direction for the tween as well. 53 00:03:25,920 --> 00:03:31,680 Now again, remember when we get past a tween info or a developer creates a new tween info instance, 54 00:03:31,680 --> 00:03:37,110 if they do not supply any values to these other properties, like let's say they only passed a time 55 00:03:37,110 --> 00:03:41,700 and leave the rest blank, then these will have their own default values and we don't have to worry 56 00:03:41,700 --> 00:03:43,230 about them being nil. 57 00:03:43,500 --> 00:03:50,520 Now the next thing a tween info needs to be passed is a property called repeat count, and that defines 58 00:03:50,520 --> 00:03:53,790 the number of times the tween repeats after tweening once. 59 00:03:53,880 --> 00:03:57,150 We also need to store the tween info. 60 00:03:57,150 --> 00:04:03,090 Dot reverses property a boolean that tells us whether or not the tween should reverse once the initial 61 00:04:03,090 --> 00:04:10,350 tween completes and tween info dot delay time is the last property which defines the amount of time 62 00:04:10,350 --> 00:04:12,690 that should elapse before the tween starts. 63 00:04:13,230 --> 00:04:17,490 So now that we have this tween data based on the tween info that was passed to our tween function, 64 00:04:17,490 --> 00:04:24,330 we can then refer to our play tween event, and we can fire to all the clients in our game that we need 65 00:04:24,330 --> 00:04:28,350 to update a tween on this instance. 66 00:04:28,770 --> 00:04:31,170 So the instance passed to this function. 67 00:04:31,170 --> 00:04:33,870 We're going to pass our tween data table. 68 00:04:33,870 --> 00:04:39,030 And then we're going to pass the goal table that represents the properties that need to be updated for 69 00:04:39,030 --> 00:04:39,750 this tween. 70 00:04:40,320 --> 00:04:44,550 Now something that's very important that we need to imitate, that the regular tween service does, 71 00:04:44,580 --> 00:04:49,770 is that we need to cancel tweens in case an instance is tweened on again. 72 00:04:49,950 --> 00:04:55,860 So let's say we call this function on a part and we want to change the keyframe to some position. 73 00:04:55,860 --> 00:04:56,220 Right. 74 00:04:56,220 --> 00:04:57,960 So we do that we call the function. 75 00:04:57,960 --> 00:04:59,940 And let's say the tween lasts five seconds. 76 00:04:59,940 --> 00:05:05,010 However let's say only one second later this function gets called again on the exact same part. 77 00:05:05,010 --> 00:05:07,410 And we've updated the position to a different area. 78 00:05:07,410 --> 00:05:13,410 Well, the issue is going to be is that if there's any discrepancies between the tween duration, one 79 00:05:13,410 --> 00:05:17,820 of the properties for the tween might get applied first before the other property of the tween gets 80 00:05:17,820 --> 00:05:18,270 applied. 81 00:05:18,270 --> 00:05:24,300 So what we need to do is we need to cancel any current tweens that are occurring on this instance before 82 00:05:24,300 --> 00:05:26,970 we apply the next tween for this instance. 83 00:05:27,210 --> 00:05:32,250 So basically what we could do is we could create a table up here and we're going to call this tween 84 00:05:32,250 --> 00:05:33,330 threads. 85 00:05:33,420 --> 00:05:39,420 Because what we're going to do is we're going to have a function that listens for when a tween completes. 86 00:05:39,420 --> 00:05:43,410 So we'll call it tween completed and it gets passed an instance. 87 00:05:44,410 --> 00:05:45,280 And the goal. 88 00:05:45,280 --> 00:05:50,290 So this function we need to call on this particular instance once this tween completes. 89 00:05:50,290 --> 00:05:53,800 So we need to calculate the duration for this tween. 90 00:05:53,800 --> 00:05:55,360 And we'll create a variable. 91 00:05:55,360 --> 00:05:58,060 We'll call it total duration for the tween. 92 00:05:58,060 --> 00:06:02,260 And what this has to be equal to is this has to be equal to our tween info. 93 00:06:03,170 --> 00:06:05,690 Dot time. 94 00:06:05,810 --> 00:06:11,930 And then we need to add along with this our tween info dot delay time. 95 00:06:11,930 --> 00:06:16,550 So we make sure to account for the time and the delay time if it exists. 96 00:06:16,880 --> 00:06:23,930 And then we need to multiply this value by the tween info dot repeat count. 97 00:06:23,930 --> 00:06:29,330 So if this tween needs to repeat multiple times, well of course the total duration for the tween is 98 00:06:29,330 --> 00:06:30,530 going to be longer. 99 00:06:30,740 --> 00:06:36,140 Now something that's very important that we need to do before we actually multiply this number to this 100 00:06:36,140 --> 00:06:36,590 value. 101 00:06:36,620 --> 00:06:40,310 Here is let's say the repeat count is zero right. 102 00:06:40,310 --> 00:06:41,480 We don't want it to repeat. 103 00:06:41,480 --> 00:06:43,340 And this tween is only going to run once. 104 00:06:43,340 --> 00:06:47,990 Well it doesn't matter what time we calculate it here because we're going to be multiplying it by zero 105 00:06:47,990 --> 00:06:50,780 which will automatically make the total duration to zero. 106 00:06:50,780 --> 00:06:55,550 So we need to also account for the time where this tween will run without repeating. 107 00:06:55,550 --> 00:06:59,240 So we're going to add plus one to the value here. 108 00:06:59,240 --> 00:07:04,580 So for example let's say we have a tween info that's going to last two seconds. 109 00:07:04,580 --> 00:07:07,670 And we have it repeat two times right. 110 00:07:07,670 --> 00:07:10,130 So we get two seconds in here. 111 00:07:10,400 --> 00:07:12,800 We don't add any delay time because there is none. 112 00:07:12,800 --> 00:07:16,430 And we multiply the two by the repeat count plus one. 113 00:07:16,430 --> 00:07:18,170 So that would be two plus one. 114 00:07:18,170 --> 00:07:21,020 Which means this tween would run a total of three times. 115 00:07:21,020 --> 00:07:24,860 So three times two would be a total duration of six seconds. 116 00:07:25,340 --> 00:07:31,070 And then what we could do is we could use the task dot delay function in the task library to spawn our 117 00:07:31,070 --> 00:07:33,650 tween completed function and a new thread. 118 00:07:33,650 --> 00:07:37,490 And the duration we need to wait is the total duration that we just calculated. 119 00:07:37,490 --> 00:07:42,500 So we want to wait this amount of time before applying the changes that our tween does. 120 00:07:42,500 --> 00:07:44,060 So we'll wait this. 121 00:07:44,060 --> 00:07:48,620 And then after this amount of time, we're going to spawn our tween completed function in a new thread. 122 00:07:48,710 --> 00:07:53,000 And the things that we need to pass to this function are going to be the instance that this tween is 123 00:07:53,000 --> 00:07:53,660 affecting. 124 00:07:53,660 --> 00:07:58,640 And we also need to pass the goal table containing all the properties we need to apply on this instance. 125 00:07:58,640 --> 00:08:06,080 So that means inside of this table here we're going to loop through every single property and value 126 00:08:06,080 --> 00:08:07,820 inside of our goal table. 127 00:08:08,360 --> 00:08:13,550 And what we're going to do is we're going to set on this instance the property. 128 00:08:16,080 --> 00:08:17,250 Equal to this value. 129 00:08:17,250 --> 00:08:22,680 So that way we're keeping track of the new properties applied to this instance after the tween completes 130 00:08:22,680 --> 00:08:24,480 on the clients end. 131 00:08:24,600 --> 00:08:30,030 Now, since this task delay function returns a thread data type, we can store that thread data type 132 00:08:30,030 --> 00:08:31,950 within our tween threads table. 133 00:08:31,980 --> 00:08:39,690 So inside of tween threads we're going to use the instance that this tween is affecting as the key inside 134 00:08:39,690 --> 00:08:40,320 of this table. 135 00:08:40,320 --> 00:08:42,420 So we can just pass our instance here. 136 00:08:42,720 --> 00:08:47,580 And it's going to store this thread that is currently being delayed until this duration is up. 137 00:08:47,580 --> 00:08:53,190 So that way if this function somehow gets called again on the same instance before it had a chance to 138 00:08:53,190 --> 00:08:59,040 execute this tween completed function, then we can go ahead and cancel the thread stopping this tween 139 00:08:59,040 --> 00:09:01,380 completed function from ever running again. 140 00:09:01,650 --> 00:09:08,160 So we could create an if statement up here and check if inside of our tween threads table we have a 141 00:09:08,160 --> 00:09:09,990 key for this instance. 142 00:09:10,020 --> 00:09:16,380 If we do, then when we need to do is we need to cancel the thread for this particular instance. 143 00:09:18,070 --> 00:09:23,110 And then once we do that, we can set inside of our tween threads table on this instance to be equal 144 00:09:23,110 --> 00:09:23,560 to nil. 145 00:09:23,560 --> 00:09:26,290 So we're basically clearing out this key value pair. 146 00:09:26,870 --> 00:09:31,490 Now we also need to clear this out within the tween threads table when our tween completes as well. 147 00:09:31,490 --> 00:09:34,790 So what we could do up here is we could just basically copy this. 148 00:09:35,480 --> 00:09:38,840 And remove it from our table before we apply the properties. 149 00:09:38,870 --> 00:09:44,180 So basically what's going on here is we pass an instance between info for that instance and then the 150 00:09:44,180 --> 00:09:45,290 goal properties. 151 00:09:45,290 --> 00:09:51,530 If this instance already has a tween being acted upon it, then we need to cancel that previous tween. 152 00:09:51,530 --> 00:09:55,310 And then we can create this new tween and apply it on our instance. 153 00:09:55,340 --> 00:10:01,670 That way, no matter what the last call of this tween function on a certain instance is guaranteed to 154 00:10:01,670 --> 00:10:04,430 be the final properties applied to the instance. 155 00:10:04,430 --> 00:10:10,400 This saves us from when this function may get called multiple times on the same instance. 156 00:10:10,920 --> 00:10:16,230 Now, what we need to do is we need to handle this tween that gets passed to our clients. 157 00:10:16,230 --> 00:10:21,450 So inside of our starter player script, we have a tween handler module script. 158 00:10:22,010 --> 00:10:22,970 Inside of here. 159 00:10:22,970 --> 00:10:26,240 What we could do is we could refer to our tween service. 160 00:10:28,410 --> 00:10:31,050 We can refer to replicated storage. 161 00:10:33,310 --> 00:10:37,330 And then we can create the table that's going to represent this tween handler. 162 00:10:37,630 --> 00:10:40,870 And we'll make sure to return it at the end of our script here. 163 00:10:43,240 --> 00:10:48,100 And now the only thing we need to do inside of our tween handler is to have an initialize function. 164 00:10:48,100 --> 00:10:50,440 So tween handler init. 165 00:10:50,650 --> 00:10:58,600 And we need to make a variable reference to that play tween event and replicated storage dot events 166 00:10:58,690 --> 00:11:02,290 dot remotes dot poi tween oops. 167 00:11:02,290 --> 00:11:04,690 And it looks like I didn't finish typing this out up there. 168 00:11:05,710 --> 00:11:10,810 And basically all we're going to do is we're going to listen for when our play tween event gets fired. 169 00:11:10,990 --> 00:11:16,630 So on client event we can connect a custom private function. 170 00:11:17,540 --> 00:11:21,710 So we can call this function on client tween event. 171 00:11:21,710 --> 00:11:27,830 And we'll get passed the instance between data for this instance and the goal table. 172 00:11:28,780 --> 00:11:32,590 And what we could do in here is we could create our own custom tween info. 173 00:11:32,590 --> 00:11:39,460 So tween info dot new and we can get our tween data table that gets passed to this function. 174 00:11:39,460 --> 00:11:46,780 And basically just use the unpack function to dump all of the data stored in here and pass it to our 175 00:11:46,780 --> 00:11:48,580 tween info dot new function. 176 00:11:48,580 --> 00:11:51,700 Then we can use our tween service to create a new tween. 177 00:11:51,700 --> 00:11:58,750 On this instance, we will pass our tween info and pass the goal table, and then we can just play it. 178 00:11:58,750 --> 00:12:03,100 And then when this event gets fired, we'll just connect it to our on client tween event. 179 00:12:03,100 --> 00:12:05,110 And that's all we need to do for that. 180 00:12:05,440 --> 00:12:10,330 Now we can go ahead and get started on scripting the functionality for our doors, and we're going to 181 00:12:10,330 --> 00:12:12,220 get to do that in the next lecture. 182 00:12:12,220 --> 00:12:13,630 So I'll see you there.